home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 176-200 / scopedisk192 / unzipv3.1 / unzip.c < prev    next >
C/C++ Source or Header  |  1995-03-19  |  24KB  |  895 lines

  1.  
  2. /*
  3.  * Copyright 1989 Samuel H. Smith;  All rights reserved
  4.  *
  5.  * Do not distribute modified versions without my permission.
  6.  * Do not remove or alter this notice or any other copyright notice.
  7.  * If you use this in your own program you must distribute source code.
  8.  * Do not use any of this in a commercial product.
  9.  *
  10.  */
  11.  
  12. /*
  13.  * UnZip - A simple zipfile extract utility
  14.  *
  15.  * Compile-time definitions:
  16.  * See the Makefile for details, explanations, and all the current
  17.  * system makerules.
  18.  *
  19.  * If you have to add a new one for YOUR system, please forward the
  20.  * new Makefile to kirsch@usasoc.soc.mil for distribution.
  21.  * Be SURE to give FULL details on your system (hardware, OS, versions,
  22.  * processor, whatever) that made it unique.
  23.  *
  24.  * REVISION HISTORY : See history.307 (or whatever current version is)
  25.  *
  26.  */
  27.  
  28. #include "unzip.h"
  29. #include "zip_proto.i"
  30.             /* v3.05 a BUNCH of ifdefs, etc.
  31.              * split out to reduce file size.
  32.              * David Kirschbaum
  33.              */
  34.  
  35. char *fnames[2] = { /* default filenames vector */
  36.     "*",
  37.     NULL
  38. };
  39. char **fnv = &fnames[0];
  40.  
  41. int tflag;      /* -t: test */
  42. int vflag;      /* -v: view directory */
  43. int cflag;      /* -c: output to stdout (JC) */
  44. int aflag;      /* -a: do ascii to ebcdic translation 2.0f */
  45.                 /*     OR <cr><nl> to <nl> conversion  */
  46. int mflag;    /* -m: map member filenames to lower case v2.0j */
  47. int CR_flag = 0; /* When last char of buffer == CR */
  48.  
  49. int members;
  50. longint csize;
  51. longint ucsize;
  52. longint tot_csize;
  53. longint tot_ucsize;
  54.  
  55.  
  56. /* ----------------------------------------------------------- */
  57. /*
  58.  * shrink/reduce working storage
  59.  *
  60.  */
  61.  
  62. int factor;
  63. /* really need only 256, but prefix_of, which shares the same
  64.    storage, is just over 16K */
  65. byte __huge followers[257][64];    /* also lzw prefix_of, s-f lit_nodes */
  66. byte __huge Slen[256];
  67.  
  68. typedef short hsize_array_integer[hsize+1]; /* was used for prefix_of */
  69. typedef byte hsize_array_byte[hsize+1];
  70.  
  71. short *prefix_of = (short *) followers; /* share reduce/shrink storage */
  72.  
  73. #ifdef    AMIGA
  74. long dummy_1_to_ensure_alignment;
  75. #endif
  76. hsize_array_byte suffix_of;     /* also s-f length_nodes */
  77.  
  78. #ifdef    AMIGA
  79. long dummy_2_to_ensure_alignment;
  80. #endif
  81. hsize_array_byte stack;         /* also s-f distance_nodes */
  82.  
  83. int codesize;
  84. int maxcode;
  85. int free_ent;
  86. int maxcodemax;
  87. int offset;
  88. int sizex;
  89.  
  90. /* Code now begins ( .. once more into the Valley of Death.. ) */
  91.  
  92.  
  93. #ifdef NOTINT16     /* v2.0c */
  94. UWORD makeword(b)
  95. byte * b;
  96.  /* convert Intel style 'short' integer to non-Intel non-16-bit
  97.   * host format
  98.   */
  99. {
  100. /*
  101.     return  ( ((UWORD) (b[1]) << 8)
  102.             | (UWORD) (b[0])
  103.             );
  104. */
  105.     return  ( ( b[1] << 8)
  106.             | b[0]
  107.             );
  108. }
  109.  
  110. longint makelong(sig)
  111. byte *sig;
  112.  /* convert intel style 'long' variable to non-Intel non-16-bit
  113.   * host format
  114.   */
  115. {
  116.     return ( ((longint) sig[3]) << 24)
  117.           + ( ((longint) sig[2]) << 16)
  118.           + ( ((longint) sig[1]) << 8)
  119.           +   ((longint)  sig[0]) ;
  120. }
  121. #endif  /* NOTINT16 */
  122.  
  123. #ifdef HIGH_LOW
  124.  
  125. void swap_bytes(UWORD *);
  126. void swap_lbytes(longint *);
  127.  
  128. void swap_bytes(wordp)
  129. UWORD *wordp;
  130.  /* convert Intel style 'short int' variable to host format */
  131. {
  132.     char *charp = (char *) wordp;
  133.     char temp;
  134.  
  135.     temp = charp[0];
  136.     charp[0] = charp[1];
  137.     charp[1] = temp;
  138. }
  139.  
  140. void swap_lbytes(longp)
  141. longint *longp;
  142.  /* convert intel style 'long' variable to host format */
  143. {
  144.     char *charp = (char *) longp;
  145.     char temp[4];
  146.  
  147.     temp[3] = charp[0];
  148.     temp[2] = charp[1];
  149.     temp[1] = charp[2];
  150.     temp[0] = charp[3];
  151.  
  152.     charp[0] = temp[0];
  153.     charp[1] = temp[1];
  154.     charp[2] = temp[2];
  155.     charp[3] = temp[3];
  156. }
  157.  
  158. #endif /* HIGH_LOW */
  159. /* ----------------------------------------------------------- */
  160.  
  161. #include "file_io.c"        /* v3.05 file-related vars, functions */
  162.  
  163. #include "unreduce.c"        /* v3.05 */
  164.  
  165. #include "unshrink.c"        /* v3.05 */
  166.  
  167. #include "unimplod.c"        /* v3.05 */
  168.  
  169. /* ---------------------------------------------------------- */
  170.  
  171. /*
  172.  Length  Method   Size  Ratio   Date    Time   CRC-32    Name
  173.  ------  ------   ----- -----   ----    ----   ------    ----
  174.   44004  Implode  13041  71%  11-02-89  19:34  88420727  DIFF3.C
  175.  */
  176.  
  177. void dir_member()
  178. {
  179.     char *method;
  180.     int ratio;
  181.     int yr, mo, dy, hh, mm;
  182.  
  183.     yr = (((lrec.last_mod_file_date >> 9) & 0x7f) + 80);
  184.     mo = ((lrec.last_mod_file_date >> 5) & 0x0f);
  185.     dy = (lrec.last_mod_file_date & 0x1f);
  186.  
  187.     hh = ((lrec.last_mod_file_time >> 11) & 0x1f);
  188.     mm = ((lrec.last_mod_file_time >> 5) & 0x3f);
  189.  
  190.     switch (lrec.compression_method)  {
  191.     case 0:
  192.         method = "Stored";
  193.         break;
  194.     case 1:
  195.         method = "Shrunk";
  196.         break;
  197.     case 2:
  198.     case 3:
  199.     case 4:
  200.     case 5:
  201.         method = "Reduced";
  202.         break;
  203.     case 6:
  204.         method = "Implode";
  205.         break;
  206.     }
  207.  
  208.     if (ucsize != 0)  {
  209.         ratio = (int) ((1000L * (ucsize - csize)) / ucsize);
  210.         if ((ratio % 10) >= 5)
  211.             ratio += 10;
  212.     }
  213.     else
  214.         ratio = 0;  /* can .zip contain 0-size file? */
  215.  
  216. #ifdef NOTINT16     /* v2.0c */
  217.     printf("%7ld  %-7s%7ld %3d%%  %02d-%02d-%02d  %02d:%02d  \
  218. %08lx  %s\n", ucsize, method, csize,
  219.         ratio / 10, mo, dy, yr, hh, mm,
  220.         lrec.crc32, filename);
  221. #else   /* !NOTINT16 */
  222.     printf("%7ld  %-7s%7ld %3d%%  %02d-%02d-%02d  %02d:%02d  \
  223. %08lx  %s\n", ucsize, method, csize,
  224.         ratio / 10, mo, dy, yr, hh, mm,
  225.         LONGI(lrec.crc32), filename);
  226. #endif  /* NOTINT16 */
  227.     tot_ucsize += ucsize;
  228.     tot_csize += csize;
  229.     ++members;
  230. }
  231.  
  232. /* ---------------------------------------------------------- */
  233.  
  234. void skip_member()
  235. {
  236.     register long pos;
  237.     long endbuf;
  238.     int offset;
  239.  
  240.     endbuf = lseek(zipfd, 0L, SEEK_CUR);    /* 1st byte beyond inbuf */
  241.     pos = endbuf - incnt;                   /* 1st compressed byte */
  242.     pos += csize;                           /* next header signature */
  243.     if (pos < endbuf)  {
  244.         incnt -= csize;
  245.         inptr += csize;
  246.     }
  247.     else  {
  248.         offset = pos % BSIZE;               /* offset within block */
  249.         pos = (pos / BSIZE) * BSIZE;        /* block start */
  250.         lseek(zipfd, pos, SEEK_SET);
  251.         incnt = read(zipfd, inbuf, INBUFSIZ);
  252.         incnt -= offset;
  253.         inptr = inbuf + offset;
  254.     }
  255. }
  256.  
  257. /* ---------------------------------------------------------- */
  258.  
  259. void extract_member()
  260. {
  261.         UWORD     b;
  262. /* for test reasons */
  263.  
  264.     bits_left = 0;
  265.     bitbuf = 0;
  266.     outpos = 0L;
  267.     outcnt = 0;
  268.     outptr = outbuf;
  269.     zipeof = 0;
  270.     crc32val = 0xFFFFFFFFL;
  271.  
  272.     zmemset(outbuf, 0, OUTBUFSIZ);
  273.     if (aflag)                          /* if we have scratchpad.. v2.0g */
  274.         zmemset(outout, 0, OUTBUFSIZ);  /* ..clear it out v2.0g */
  275.       
  276.     if (tflag)
  277.         fprintf(stderr, "Testing: %-12s ", filename);
  278.     else {
  279.         if(!mapped_name())    /* member name conversion failed  v2.0j */
  280.         exit(1);        /* choke and die v2.0j */
  281.  
  282.         /* create the output file with READ and WRITE permissions */
  283.         if (create_output_file())
  284.             return; /* was exit(1); */
  285.     }
  286.     switch (lrec.compression_method) {
  287.  
  288.     case 0: {   /* stored */
  289.             if (!tflag)
  290.                 fprintf(stderr, " Extracting: %-12s ", filename);
  291.             if (cflag) fprintf(stderr, "\n");
  292.             while (ReadByte(&b))
  293.                 OUTB(b);
  294.         }
  295.         break;
  296.  
  297.     case 1: {       /* shrunk */
  298.             if (!tflag)
  299.                 fprintf(stderr, "UnShrinking: %-12s ", filename);
  300.             if (cflag) fprintf(stderr, "\n");
  301.             unShrink();
  302.         }
  303.         break;
  304.  
  305.     case 2:
  306.     case 3:
  307.     case 4:
  308.     case 5: {
  309.             if (!tflag)
  310.                 fprintf(stderr, "  Expanding: %-12s ", filename);
  311.             if (cflag) fprintf(stderr, "\n");
  312.             unReduce();
  313.         }
  314.         break;
  315.  
  316.     case 6: {
  317.             if (!tflag)
  318.                 fprintf(stderr, "  Exploding: %-12s ", filename);
  319.             if (cflag) fprintf(stderr, "\n");
  320.             unImplode();
  321.         }
  322.         break;
  323.  
  324.     default:
  325.         fprintf(stderr, "Unknown compression method.");
  326.     }
  327.  
  328.     /* write the last partial buffer, if any */
  329.     FlushOutput ();
  330.  
  331.     if (!tflag)  {
  332. #ifndef UNIX
  333.         /* set output file date and time */
  334.         set_file_time();
  335.         close(outfd);
  336. #else
  337.         close(outfd);
  338.         /* set output file date and time */
  339.         set_file_time();
  340. #endif
  341.     }
  342.  
  343.     crc32val = ~crc32val;
  344. #ifdef NOTINT16     /* v2.0c */
  345.     if (crc32val != lrec.crc32)
  346.         fprintf(stderr, " Bad CRC %08lx  (should be %08lx)", crc32val,
  347.             lrec.crc32);
  348. #else   /* !NOTINT16 */
  349.     if (crc32val != LONGI(lrec.crc32))
  350.         fprintf(stderr, " Bad CRC %08lx  (should be %08lx)", crc32val,
  351.             LONGI(lrec.crc32));
  352. #endif  /* NOTINT16 */
  353.  
  354.     else if (tflag)
  355.         fprintf(stderr, " OK");
  356.  
  357.     fprintf(stderr, "\n");
  358. }
  359.  
  360.  
  361. /* ---------------------------------------------------------- */
  362.  
  363. void get_string(len, s)
  364. int len;
  365. char *s;
  366. {
  367.     readbuf(zipfd, s, len);
  368.     s[len] = 0;
  369.  
  370. #ifdef EBCDIC           /* translate the filename to ebcdic */
  371.     a_to_e( s );        /* A.B.  03/21/90                   */
  372. #endif
  373. }
  374.  
  375.  
  376. /* ---------------------------------------------------------- */
  377.  
  378. void process_local_file_header(fnamev)
  379. char **fnamev;
  380. {
  381.     int extracted;
  382. #ifdef NOTINT16     /* v2.0c */
  383.     local_byte_header brec;
  384. #endif
  385.  
  386. #ifndef NOTINT16    /* v2.0c */
  387.     readbuf(zipfd, (char *) &lrec, sizeof(lrec));   /* v2.0b */
  388. #else   /* NOTINT16 */
  389.     readbuf(zipfd, (char *) &brec, sizeof(brec));
  390.  
  391.     lrec.version_needed_to_extract =
  392.         makeword(brec.version_needed_to_extract);
  393.     lrec.general_purpose_bit_flag =
  394.         makeword(brec.general_purpose_bit_flag);
  395.     lrec.compression_method =
  396.         makeword(brec.compression_method);
  397.     lrec.last_mod_file_time =
  398.         makeword(brec.last_mod_file_time);
  399.     lrec.last_mod_file_date =
  400.         makeword(brec.last_mod_file_date);
  401.     lrec.crc32 =
  402.         makelong(brec.crc32);
  403.     lrec.compressed_size =
  404.         makelong(brec.compressed_size);
  405.     lrec.uncompressed_size =
  406.         makelong(brec.uncompressed_size);
  407.     lrec.filename_length =
  408.         makeword(brec.filename_length);
  409.     lrec.extra_field_length =
  410.         makeword(brec.extra_field_length);
  411. #endif  /* NOTINT16 */
  412.  
  413. #ifdef HIGH_LOW
  414.     swap_bytes(&lrec.filename_length);
  415.     swap_bytes(&lrec.extra_field_length);
  416.     swap_lbytes(LONGIP(lrec.compressed_size));
  417.     swap_lbytes(LONGIP(lrec.uncompressed_size));
  418.     swap_bytes(&lrec.compression_method);
  419.     swap_bytes(&lrec.version_needed_to_extract);
  420.     swap_bytes(&lrec.general_purpose_bit_flag);
  421.     swap_bytes(&lrec.last_mod_file_time);
  422.     swap_bytes(&lrec.last_mod_file_date);
  423.     swap_lbytes(LONGIP(lrec.crc32));
  424. #endif  /* HIGH_LOW */
  425.  
  426. #ifdef NOTINT16     /* v2.0c */
  427.     csize = lrec.compressed_size;
  428.     ucsize = lrec.uncompressed_size;
  429. #else   /* !NOTINT16 */
  430.     csize = LONGI(lrec.compressed_size);
  431.     ucsize = LONGI(lrec.uncompressed_size);
  432. #endif  /* NOTINT16 */
  433.  
  434.     get_string(lrec.filename_length, filename);
  435.     get_string(lrec.extra_field_length, extra);
  436.  
  437.     extracted = 0;
  438.     for (--fnamev; *++fnamev; )  {
  439.         if (match(filename, *fnamev))  {
  440.             if (vflag)
  441.                 dir_member();
  442.             else  {
  443.                 extract_member();
  444.                 extracted = 1;
  445.             }
  446.             break;
  447.         }
  448.     }
  449.     if (!extracted)
  450.         skip_member();
  451. }
  452.  
  453.  
  454. /* ---------------------------------------------------------- */
  455.  
  456. void process_central_file_header()
  457. {
  458.     central_directory_file_header rec;
  459.     char filename[STRSIZ];
  460.     char extra[STRSIZ];
  461. /*  char comment[STRSIZ]; v2.0b using global comment so we can display it */
  462.  
  463. #ifdef NOTINT16     /* v2.0c */
  464.     central_directory_byte_header byterec;
  465. #endif
  466.  
  467. #ifndef NOTINT16    /* v2.0c */
  468.     readbuf(zipfd, (char *) &rec, sizeof(rec)); /* v2.0b */
  469. #else   /* NOTINT16 */
  470.     readbuf(zipfd, (char *) &byterec, sizeof(byterec) );        /* v2.0c */
  471.  
  472.     rec.version_made_by =
  473.         makeword(byterec.version_made_by);
  474.     rec.version_needed_to_extract =
  475.         makeword(byterec.version_needed_to_extract);
  476.     rec.general_purpose_bit_flag =
  477.         makeword(byterec.general_purpose_bit_flag);
  478.     rec.compression_method =
  479.         makeword(byterec.compression_method);
  480.     rec.last_mod_file_time =
  481.         makeword(byterec.last_mod_file_time);
  482.     rec.last_mod_file_date =
  483.         makeword(byterec.last_mod_file_date);
  484.     rec.crc32 =
  485.         makelong(byterec.crc32);
  486.     rec.compressed_size =
  487.         makelong(byterec.compressed_size);
  488.     rec.uncompressed_size =
  489.         makelong(byterec.uncompressed_size);
  490.     rec.filename_length =
  491.         makeword(byterec.filename_length);
  492.     rec.extra_field_length =
  493.         makeword(byterec.extra_field_length);
  494.     rec.file_comment_length =
  495.         makeword(byterec.file_comment_length);
  496.     rec.disk_number_start =
  497.         makeword(byterec.disk_number_start);
  498.     rec.internal_file_attributes =
  499.         makeword(byterec.internal_file_attributes);
  500.     rec.external_file_attributes =
  501.         makeword(byterec.external_file_attributes);
  502.     rec.relative_offset_local_header =
  503.         makelong(byterec.relative_offset_local_header);
  504. #endif  /* NOTINT16 */
  505.  
  506. #ifdef HIGH_LOW
  507.     swap_bytes(&rec.filename_length);
  508.     swap_bytes(&rec.extra_field_length);
  509.     swap_bytes(&rec.file_comment_length);
  510. #endif
  511.  
  512.     get_string(rec.filename_length, filename);
  513.     get_string(rec.extra_field_length, extra);
  514.     get_string(rec.file_comment_length, comment);
  515. }
  516.  
  517.  
  518. /* ---------------------------------------------------------- */
  519.  
  520. void process_end_central_dir()
  521. {
  522.     end_central_dir_record rec;
  523. /*  char comment[STRSIZ]; v2.0b made global */
  524.  
  525. #ifdef NOTINT16     /* v2.0c */
  526.     end_central_byte_record byterec;
  527. #endif
  528.  
  529. #ifndef NOTINT16    /* v2.0c */
  530.     readbuf(zipfd, (char *) &rec, sizeof(rec)); /* v2.0b */
  531. #else   /* NOTINT16 */
  532.     readbuf(zipfd, (char *) &byterec, sizeof(byterec) );
  533.  
  534.     rec.number_this_disk =
  535.         makeword(byterec.number_this_disk);
  536.     rec.number_disk_with_start_central_directory =
  537.         makeword(byterec.number_disk_with_start_central_directory);
  538.     rec.total_entries_central_dir_on_this_disk =
  539.         makeword(byterec.total_entries_central_dir_on_this_disk);
  540.     rec.total_entries_central_dir =
  541.         makeword(byterec.total_entries_central_dir);
  542.     rec.size_central_directory =
  543.         makelong(byterec.size_central_directory);
  544.     rec.offset_start_central_directory =
  545.         makelong(byterec.offset_start_central_directory);
  546.     rec.zipfile_comment_length =
  547.         makeword(byterec.zipfile_comment_length);
  548. #endif  /* NOTINT16 */
  549.  
  550. #ifdef HIGH_LOW
  551.     swap_bytes(&rec.zipfile_comment_length);
  552. #endif
  553.  
  554.     /* There seems to be no limit to the zipfile
  555.        comment length.  Some zipfiles have comments
  556.        longer than 256 bytes.  Currently no use is
  557.        made of the comment anyway.
  558.      */
  559. /* #if 0
  560.  * v2.0b Enabling comment display
  561.  */
  562.     get_string(rec.zipfile_comment_length, comment);
  563. /* #endif */
  564. }
  565.  
  566.  
  567. /* ---------------------------------------------------------- */
  568.  
  569. void process_headers()
  570. {
  571.     int ratio;
  572.     long sig;
  573.  
  574. #ifdef NOTINT16     /* v2.0c */
  575.     byte sigbyte[4];
  576. #endif
  577.  
  578.     if (vflag)  {
  579.         members = 0;
  580.         tot_ucsize = tot_csize = 0;
  581.         printf("\n Length  Method   Size  Ratio   Date    Time   \
  582. CRC-32    Name\n ------  ------   ----- -----   ----    ----   ------    \
  583. ----\n");
  584.     }
  585.  
  586.     while (1) {
  587. #ifdef NOTINT16     /* v2.0c */
  588.     if (readbuf(zipfd, (char *) sigbyte, 4) != 4)
  589. #else   /* !NOTINT16 */
  590.     if (readbuf(zipfd, (char *) &sig, sizeof(sig)) != sizeof(sig))
  591. #endif  /* NOTINT16 */
  592.         return;
  593.  
  594. #ifdef NOTINT16     /* v2.0c */
  595.         sig = makelong(sigbyte);
  596. #endif
  597.  
  598. #ifdef HIGH_LOW
  599.         swap_lbytes(&sig);
  600. #endif
  601.  
  602.         if (sig == LOCAL_FILE_HEADER_SIGNATURE)
  603.             process_local_file_header(fnv);
  604.         else if (sig == CENTRAL_FILE_HEADER_SIGNATURE)
  605.             process_central_file_header();
  606.         else if (sig == END_CENTRAL_DIR_SIGNATURE) {
  607.             process_end_central_dir();
  608.             break;
  609.         }
  610.         else {
  611.             fprintf(stderr, "Invalid Zipfile Header\n");
  612.             return;
  613.         }
  614.     }
  615.     if (vflag)  {
  616.         if (tot_ucsize != 0)  {
  617.             ratio = (int) ((1000L * (tot_ucsize-tot_csize))
  618.                     / tot_ucsize);
  619.             if ((ratio % 10) >= 5)
  620.                 ratio += 10;
  621.         }
  622.         else
  623.             ratio = 0;
  624.         printf(" ------          ------  \
  625. ---                             -------\n\
  626. %7ld         %7ld %3d%%                             %7d\n",
  627.         tot_ucsize, tot_csize, ratio / 10, members);
  628.  
  629.         if( comment[0] )                /* v2.0b */
  630.             printf("%s\n",comment);     /* v2.0b */
  631.     }
  632. }
  633.  
  634.  
  635. /* ---------------------------------------------------------- */
  636. /* v3.04 Patch to enable processing of self-extracting ".EXE"
  637.  * (and other) files that might have weird junk before the first
  638.  * actual file member.
  639.  * I don't THINK anyone'll have problems with this .. but just in case,
  640.  * you can disable the entire mess by enabling the "NOSKIP" ifdef.
  641.  * (up near code top).
  642.  * Thanks to Warner Losh for this patch.
  643.  */
  644. #ifndef NOSKIP
  645. void skip_to_signature()
  646. {
  647.     static char pk[] = "PK";
  648.     int i, nread;
  649.     unsigned char ch;
  650.     extern int errno;
  651.     
  652.     errno = 0;            /* Be sure we start with 0 */
  653.     do {
  654.         /*
  655.          * Search for "PK"
  656.          */
  657.         i = 0;
  658.         while ((nread = read (zipfd, &ch, 1)) && i < 2) {
  659.             if (ch == pk[i]) {
  660.                 i++;
  661.             }
  662.             else {
  663.                 if (ch == pk[0])
  664.                     i = 1;
  665.                 else
  666.                     i = 0;
  667.             }
  668.         }
  669.     if (errno || nread==0) {    /* read err or EOF */
  670.         fprintf(stderr, "Unable to find a valid header signature. Aborting.\n");
  671.         exit (2);
  672.     }
  673.     } while (ch > 20);
  674.  
  675.     /*
  676.      * We have now read 3 characters too many, so we backup.
  677.      */
  678.     lseek (zipfd, -3L, SEEK_CUR);
  679. }
  680. #endif        /* NOSKIP */
  681.  
  682.  
  683. void process_zipfile()
  684. {
  685.     /*
  686.      * open the zipfile for reading and in BINARY mode to prevent cr/lf
  687.      * translation, which would corrupt the bitstreams
  688.      */
  689.  
  690.     if (open_input_file())
  691.         exit(1);
  692.  
  693. #ifndef NOSKIP        /* v3.03 */
  694.     skip_to_signature();    /* read up to first "PK%" v3.03 */
  695. #endif
  696.     process_headers();
  697.  
  698.     close(zipfd);
  699. }
  700.  
  701. /* ---------------------------------------------------------- */
  702.  
  703. void usage()        /* v2.0j */
  704. {
  705.  
  706. #ifdef EBCDIC                              /* A.B. 03/20/90   */
  707.   char *astring = "-a  ascii to ebcdic conversion";
  708. #else
  709.   char *astring = "-a  convert to unix textfile format (CR LF => LF)";    /* v3.04 */
  710. #endif
  711.  
  712. fprintf(stderr, "\n%s\nCourtesy of:  S.H.Smith  and  The Tool Shop BBS,  (602) 279-2673.\n\n",VERSION);
  713. fprintf(stderr, "Usage:  unzip [-tcamv] file[.zip] [filespec...]\n\
  714.   -t  test member files\n\
  715.   -c  output to stdout\n\
  716.   %s\n\
  717.   -m  map extracted filenames to lowercase\n\
  718.   -v  view directory\n",astring);
  719.     exit(1);
  720. }
  721.  
  722. /* ---------------------------------------------------------- */
  723.  
  724. /*
  725.  * main program
  726.  *
  727.  */
  728.  
  729. void main(argc, argv)
  730. int argc;
  731. char **argv;
  732. {
  733.     char *s;
  734.     int c;
  735. #ifndef    AMIGA
  736.     struct stat statbuf;        /* v3.03 */
  737. #endif    /* AMIGA */
  738.  
  739. #ifdef M030
  740.  
  741. #include <exec/types.h>
  742. #include <exec/execbase.h>
  743.  struct ExecBase **execbaseptr=(struct ExecBase **)4L;
  744.  UWORD cpuid;
  745.  struct ExecBase *execbase;
  746.  
  747.  execbase = *execbaseptr;
  748.  cpuid = execbase->AttnFlags;
  749.  if (!(cpuid & AFF_68020))
  750.   {
  751.    printf("You need a 68020 to run this hyperQRT program\n");
  752.    exit(0);
  753.   }
  754. #endif
  755.  
  756. #ifdef DEBUG_STRUC                      /* v2.0e */
  757. printf("local_file_header size: %X\n",
  758.     sizeof(struct local_file_header) );
  759. printf("local_byte_header size: %X\n",
  760.     sizeof(struct local_byte_header) );
  761.  
  762. printf("central directory header size: %X\n",
  763.     sizeof(struct central_directory_file_header) );
  764. printf("central directory byte header size: %X\n",
  765.     sizeof(struct central_directory_byte_header) );
  766.  
  767. printf("end central dir record size: %X\n",
  768.     sizeof(struct end_central_dir_record) );
  769. printf("end central dir byte record size: %X\n",
  770.     sizeof(struct end_central_byte_record) );
  771. #endif
  772.  
  773.     while (--argc > 0 && (*++argv)[0] == '-')  {
  774.         s = argv[0] + 1;
  775. #ifndef __TURBOC__
  776.         while (c = *s++)  {
  777. #else
  778.         while ((c = *s++) != '\0') {      /* v2.0b */
  779. #endif
  780.  
  781. /* Something is SERIOUSLY wrong with my host's tolower() function! */
  782. /* #ifndef BSD */
  783. /*            switch (tolower(c))  { */
  784. /* #else */
  785.             switch(c) {
  786. /* #endif */
  787.             case ('T'):
  788.             case ('t'):
  789.                 ++tflag;
  790.                 break;
  791.             case ('V'):
  792.             case ('v'):
  793.                 ++vflag;
  794.                 break;
  795.             case ('C'):
  796.             case ('c'):
  797.                 ++cflag;
  798. #ifdef EBCDIC
  799.                 ++aflag;       /* This is so you can read it on the screen */
  800. #endif                         /*  A.B.  03/24/90                          */
  801.                 break;
  802.             case ('A'):
  803.             case ('a'):
  804.                 ++aflag;
  805.                 break;
  806.         case ('M'):        /* map filename flag v2.0j */
  807.         case ('m'):
  808.         ++mflag;
  809.         break;
  810.             default:
  811.                 usage();
  812.                 break;
  813.             }
  814.         }
  815.     }
  816. /*  I removed the filter for the a and c flags so they could be used together */
  817. /*  Especially on EBCDIC based systems where you would want to read the text  */
  818. /*  on the screen.  Allan Bjorklund.  03/24/90                                */
  819.  
  820.     if ((tflag && vflag) || (tflag && cflag) || (vflag && cflag) ||
  821.         (tflag && aflag) || (aflag && vflag))
  822.  
  823.     {
  824.         fprintf(stderr, "only one of -t, -c, -a, or -v\n");
  825.         exit(1);
  826.     }
  827.     if (argc-- == 0)
  828.         usage();
  829.  
  830.     /* .ZIP default if none provided by user */
  831.     strcpy(zipfn, *argv++);
  832. /* v2.0b This doesn't permit paths like "..\dir\filename" */
  833.  
  834. #ifdef REALOLDSTUFF        /* v3.02 */
  835. #ifdef OLDSTUF
  836.     if (strchr(zipfn, '.') == NULL)
  837.         strcat(zipfn, ZSUFX);
  838. #else    /* v2.0b New code */
  839.  
  840.     c = strlen(zipfn);
  841.     if ( (c < 5)                             /* less than x.zip */
  842.       || (strcmp (&zipfn[c-4], ZSUFX) != 0)) /* v2.0b type doesn't
  843.                                               * match */
  844.         strcat (zipfn, ZSUFX);
  845. #endif
  846. #else                /* v3.02 */
  847. #ifdef    AMIGA
  848.     c = strlen(zipfn);
  849.     if ( (c < 5)                             /* less than x.zip */
  850.       || (stricmp (&zipfn[c-4], ZSUFX) != 0)) /* case-insensitive */
  851.         strcat (zipfn, ZSUFX);
  852. #else
  853.       /*
  854.        * OK, first check to see if the name is as given.  If it is
  855.        * found as given, then we don't need to bother adding the
  856.        * ZSUFX.  If it isn't found, then add the ZSUFX.  We don't
  857.        * check to see if this results in a good name, but that check
  858.        * will be done later.
  859.        */
  860.     if(stat (zipfn, &statbuf))        /* v3.02 */
  861.         strcat (zipfn, ZSUFX);        /* v3.02 */
  862. #endif    /* AMIGA */
  863.  
  864. #endif    /* not REALOLDSTUF */
  865.       
  866.     /* if any member file specs on command line, set filename
  867.        pointer to point to them. */
  868.  
  869.     if (argc != 0)
  870.         fnv = argv;
  871.  
  872.         /* allocate i/o buffers */
  873.     inbuf = (byte *) (malloc(INBUFSIZ));
  874.     outbuf = (byte *) (malloc(OUTBUFSIZ));
  875.  
  876.     /* v2.0g Hacked Allan's code.  No need allocating an ascebc
  877.      * scratch buffer unless we're doing translation.
  878.      */
  879.  
  880.     if(aflag)                           /* we need an ascebc scratch v2.0g */
  881.         outout = (byte *) (malloc(OUTBUFSIZ)); /* ..so allocate it v2.0g */
  882.     else
  883.         outout = outbuf;                /* just point to outbuf v2.0g */
  884.  
  885.     if ((inbuf == NULL) || (outbuf == NULL) || (outout == NULL)) {  /* v2.0g */
  886.         fprintf(stderr, "Can't allocate buffers!\n");
  887.         exit(1);
  888.     }
  889.  
  890.     /* do the job... */
  891.     process_zipfile();
  892.     exit(0);
  893. }
  894.  
  895.